/*
 * 版权所有 (C) 2015 知启蒙(ZHIQIM) 保留所有权利。[遇见知启蒙，邂逅框架梦]
 * 
 * https://zhiqim.org/project/zhiqim_framework/zhiqim_kernel.htm
 *
 * Zhiqim Kernel is licensed under Mulan PSL v2.
 * You can use this software according to the terms and conditions of the Mulan PSL v2.
 * You may obtain a copy of Mulan PSL v2 at:
 *          http://license.coscl.org.cn/MulanPSL2
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PSL v2 for more details.
 */
package org.zhiqim.kernel.logging.logger;

import java.lang.reflect.Method;
import java.util.HashMap;

import org.zhiqim.kernel.logging.Log;
import org.zhiqim.kernel.logging.Logger;
import org.zhiqim.kernel.util.Classes;

/**
 * 适配Log4j的日志，只支持三种，DEBUG,INFO,ERROR，对应FINE,INFO,SEVERE
 *
 * @version v1.0.0 @author zouzhigang 2016-1-9 新建与整理
 */
public class Log4jLogger implements Logger
{
    //以下为日志输出器获取属性
    private Method logerNameMethod;
    private Method logClassMethod;
    
    //以下为日志输出方法属性
    private HashMap<Integer, Method> logMap = new HashMap<Integer, Method>();
    private HashMap<Integer, Method> isMap = new HashMap<Integer, Method>();
    
    @Override /** 初始化加载 */
    public boolean load()
    {
        //第一步，判断Log4j类在不在
        Class<?> log4jLogger = Classes.forName(LOG4J_LOGGER_CLASS);
        if (log4jLogger == null)
        {
            System.out.println("配置的Log4j日志包不存在");
            return false;
        }
        
        //第二步，找到Log4j类使用的12个方法
        for (Method method :log4jLogger.getMethods())
        {
            if (Classes.isStaticMethod(method))
            {//找到Logger.getLogger(String)和Logger.getLogger(Class)两个方法
                if (!LOG4J_LOGGER_METHOD.equals(method.getName()))
                    continue;
                
                Class<?>[] classes = method.getParameterTypes();
                if (classes.length != 1)
                    continue;
                
                if (classes[0] == String.class)
                    logerNameMethod = method;
                else if (classes[0] == Class.class)
                    logClassMethod = method;
            }
            else
            {//找到5个判断方法和5个操作方法
                Class<?> returnClass = method.getReturnType();
                Class<?>[] classes = method.getParameterTypes();
                if (returnClass == boolean.class && classes.length == 0)
                {//5个判断方法
                    if (LOG4J_LOGGER_IS_DEBUG.equals(method.getName()))
                        isMap.put(DEBUG, method);
                    else if (LOG4J_LOGGER_IS_INFO.equals(method.getName()))
                        isMap.put(INFO, method);
                    else if (LOG4J_LOGGER_IS_ERROR.equals(method.getName()))
                        isMap.put(ERROR, method);
                    else if (LOG4J_LOGGER_IS_WARN.equals(method.getName()))
                        isMap.put(WARN, method);
                    else if (LOG4J_LOGGER_IS_FATAL.equals(method.getName()))
                        isMap.put(FATAL, method);
                }
                else if (returnClass == void.class && classes.length == 2 && classes[0] == Object.class && classes[1] == Throwable.class)
                {//5个操作方法
                    if (LOG4J_LOGGER_DEBUG.equals(method.getName()))
                        logMap.put(DEBUG, method);
                    else if (LOG4J_LOGGER_INFO.equals(method.getName()))
                        logMap.put(INFO, method);
                    else if (LOG4J_LOGGER_ERROR.equals(method.getName()))
                        logMap.put(ERROR, method);
                    else if (LOG4J_LOGGER_WARN.equals(method.getName()))
                        logMap.put(WARN, method);
                    else if (LOG4J_LOGGER_FATAL.equals(method.getName()))
                        logMap.put(FATAL, method);
                }
            }
        }
        
        if (logerNameMethod == null || logClassMethod == null || isMap.size() != 5 && logMap.size() != 5)
        {
            System.out.println("配置的Log4j日志包不正确");
            return false;
        }
        
        return true;
    }
    
    @Override /** 日志记录器记录日志 */
    public void append(Log log, int level, String message, Throwable throwable)
    {
        try
        {
            Object obj = null;
            if (log.getLogClass() != null)
                obj = logClassMethod.invoke(null, log.getLogClass());
            else
                obj = logerNameMethod.invoke(null, log.getLogName());
            
            Method method = logMap.get(level);
            method.invoke(obj, message, throwable);
        }
        catch(Exception e)
        {
            e.printStackTrace();
        }
    }
    
    @Override /** 判断日志级别是否开启 */
    public boolean isEnabled(Log log, int level)
    {
        try
        {
            Object obj = null;
            if (log.getLogClass() != null)
                obj = logClassMethod.invoke(null, log.getLogClass());
            else
                obj = logerNameMethod.invoke(null, log.getLogName());
            
            Method method = isMap.get(level);
            return (Boolean)method.invoke(obj);
        }
        catch(Exception e)
        {
            e.printStackTrace();
            return false;
        }
    }
}
